// InfiniteScroll.tsx
import React, { useEffect, useRef, useState } from 'react';
import { ScrollView, View, Text } from '@tarojs/components';
import classNames from 'classnames';
import './index.less';

export interface InfiniteScrollProps {
  /** 加载更多的回调 */
  loadMore: () => void;
  /** 是否还有更多数据 */
  hasMore: boolean;
  /** 是否正在加载 */
  loading: boolean;
  /** 滚动到底部触发的距离阈值(px) */
  threshold?: number;
  /** 容器样式 */
  style?: React.CSSProperties;
  /** 自定义类名 */
  className?: string;
  /** 列表内容：页面传入的 jsx */
  content?: React.ReactNode;
  /** 传入数据的长度：为0则展示空页面 */
  dataList?: any[];

  // 父层自管刷新
  refresherTriggered?: boolean;
  // 父层触发刷新（可返回 Promise；若不返回也能用）
  handleRefresh?: () => void | Promise<any>;

  /** 受控滚动恢复 */
  scrollTop?: number;
  /**  滚动时回传当前 scrollTop，父层保存 */
  onScrollTopChange?: (top: number) => void;

  /** 可选：忘关兜底超时（ms） */
  refreshTimeoutMs?: number; // 默认 8000
}

const isPromise = (v: any) => !!v && typeof v.then === 'function';

const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
  loadMore,
  hasMore,
  loading,
  threshold = 50,
  style,
  className,
  content,
  dataList,
  handleRefresh,
  refresherTriggered, // 若传，走受控；不传则内部自管
  scrollTop,
  onScrollTopChange,
  refreshTimeoutMs = 8000,
}) => {
  // === 受控判断 ===
  const controlled = typeof refresherTriggered === 'boolean';

  // === 非受控内部刷新态 ===
  const [innerRefreshing, setInnerRefreshing] = useState(false);

  // === 受控模式下的“视觉强制关闭”标记（不修改父级值，只影响展示）===
  const [forceCloseRefresh, setForceCloseRefresh] = useState(false);

  // === 统一展示层刷新判定（受控 + 强制关闭叠加考虑）===
  const isRefreshingDisplay = controlled
    ? !!refresherTriggered && !forceCloseRefresh
    : innerRefreshing;

  // === 刷新超时兜底（受控 & 非受控通吃）===
  const timeoutRef = useRef<any>(null);
  useEffect(() => {
    if (isRefreshingDisplay) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = setTimeout(() => {
        if (controlled) {
          // 父级没关就做“视觉强关”，把动画收掉，避免三个点悬挂
          setForceCloseRefresh(true);
        } else {
          // 非受控直接内部关
          setInnerRefreshing(false);
        }
      }, refreshTimeoutMs);
      return () => clearTimeout(timeoutRef.current);
    }
    // 不在刷新：清理 & 复位
    clearTimeout(timeoutRef.current);
    setForceCloseRefresh(false);
  }, [isRefreshingDisplay, controlled, refreshTimeoutMs]);

  // 当父层后来真的把 refresherTriggered 置回 false，撤销强关标记，状态回归正常
  useEffect(() => {
    if (controlled && !refresherTriggered) {
      setForceCloseRefresh(false);
    }
  }, [controlled, refresherTriggered]);

  // === 下拉开始 ===
  const onRefresherRefresh = () => {
    if (!handleRefresh) return;

    if (controlled) {
      // 受控：完全交给父层开关；这里也避免父层未返回 Promise 造成的异常吞掉
      const ret = handleRefresh();
      if (isPromise(ret)) {
        (ret as Promise<any>).catch(() => {});
      }
      return;
    }

    // 非受控：组件自己开关刷新态
    if (innerRefreshing) return; // 防重入
    setInnerRefreshing(true);
    const ret = handleRefresh();
    if (isPromise(ret)) {
      (ret as Promise<any>)
        .catch(() => {})
        .finally(() => setInnerRefreshing(false));
    } else {
      // 父层没返回 Promise，也能工作：下一帧自动关闭
      Promise.resolve().then(() => setInnerRefreshing(false));
    }
  };

  // === 系统“中止/复位”事件（微信下拉被打断/回弹）===
  const onRefresherAbort = () => {
    if (controlled) {
      // 受控：视觉收口，避免动画悬挂
      setForceCloseRefresh(true);
    } else {
      setInnerRefreshing(false);
    }
  };
  const onRefresherRestore = () => {
    // 某些机型回弹时会触发，确保非受控状态一致
    if (!controlled) setInnerRefreshing(false);
  };

  const onLower = () => {
    if (!loading && hasMore) loadMore();
  };

  const onScroll = (e: any) => {
    const top = e?.detail?.scrollTop ?? 0;
    onScrollTopChange?.(top);
  };

  return (
    <ScrollView
      className={classNames('infinite-scroll', className)}
      style={{ height: '100%', ...style }}
      scrollY
      // 刷新进行中时不透传 scrollTop，避免与系统刷新位移冲突（使用展示态）
      {...(!isRefreshingDisplay && scrollTop !== undefined
        ? { scrollTop }
        : {})}
      lowerThreshold={threshold}
      enableBackToTop
      scrollAnchoring={false}
      // 开启下拉刷新：只要提供了 handleRefresh
      refresherEnabled={!!handleRefresh}
      refresherTriggered={isRefreshingDisplay}
      onRefresherRefresh={onRefresherRefresh}
      onRefresherAbort={onRefresherAbort}
      onRefresherRestore={onRefresherRestore}
      onScrollToLower={onLower}
      onScroll={onScroll}
    >
      {content}
      <View className="infinite-footer">
        {loading && <Text>加载中...</Text>}
        {!loading && hasMore && dataList && dataList.length > 0 && (
          <Text>上拉加载更多</Text>
        )}
        {!loading && !hasMore && dataList && dataList.length > 0 && (
          <Text>没有更多了</Text>
        )}
      </View>
    </ScrollView>
  );
};

export default InfiniteScroll;
